iT邦幫忙

2021 iThome 鐵人賽

DAY 24
0
Modern Web

從零開始學習 Next.js系列 第 24

Day24 - 遇到 404 或 500 怎麼辦,客製化錯誤頁面

  • 分享至 

  • xImage
  •  

前言

在「錯誤捕捉、全域 CSS、共用 Layout,就用 _app.tsx 來搞定吧!」這邊文章中有提到,目前在 Next.js 的 error boundary 無法捕捉到 SSR 發生的錯誤,會一律回 HTTP 500 給使用者,因此使用者會看到相對應的 500 畫面。

而在 Next.js 客製化 404 與 500 的頁面是很容易的一件事,就像是 App 與 Document 一樣,都是在 pages/ 這個資料夾裡面依照規範定義檔案名稱,就可以輕易地客製化這兩個頁面。

404 頁面

可以透過 getStaticProps 在 SSG 階段傳入一些資料

要客製化 404 的頁面必須在 pages/ 資料夾中新增一個檔案為 404.tsx ,這個檔案將會以 SSG 打包成靜態的 HTML 檔案:

// pages/404.tsx
const Custom404 = () => {
  return <div>Custom 404 page</div>;
};

export default Custom404;

如果一個 url 無法匹配 file-based routing 的機制,或是在 getStaticsPropsgetServerSideProps 回傳 { notFound: true } ,伺服器就會直接回傳這個 404 的頁面,不用再經過其他的運算。

500 頁面

可以透過 getStaticProps 在 SSG 階段傳入一些資料

要客製化 500 的頁面必須在 pages/ 資料夾中新增一個檔案為 500.tsx ,這個檔案將會以 SSG 打包成靜態的 HTML 檔案:

// pages/500.tsx
const Custom500 = () => {
  return <div>Custom 500 page</div>;
};

export default Custom500;

像是 getServerSideProps 在運行時發生錯誤,或是頁面中發生錯誤都可能會造成 500,此時 Next.js 的伺服器就會回傳這個頁面給使用者。

Error page

這個頁面是用來處理除了 404 跟 500 以外的錯誤,而且同時包含客戶端與伺服器端錯誤。 React 的 error boundary - componentDidCatch 無法處理 SSR 發生的錯誤,但是在 Next.js 中可以經由這個檔案來捕捉錯誤,並回傳相對應的訊息給使用者。

雖然 error page 的作用跟 error boundary 很像,但是 error boundary 真正要做的事情是透過 **componentDidCatch 捕捉錯誤本身**,你可以對錯誤本身進行處理。然而在 error page 中假設遇到的是客戶端的錯誤,實際上只是用來告訴使用者有錯誤,可是這樣一定不能滿足工程團隊的需求,因為工程團隊需要知道使用者實際上遇到的錯誤,所以需要使用 error boundary 來捕捉錯誤。

如此一來,在 Next.js 中其實可以考慮切分錯誤處理的職責,像是 error boundary 負責捕捉錯誤,並且紀錄錯誤訊息至伺服器,但是並不會處理顯示的職責,而顯示錯誤訊息則交給 error page,這樣才不會讓錯誤處理的職責散落程式碼各處,也可以讓後續維護的人更快速理解程式碼的架構。

import { NextPageContext, NextPage } from "next";

interface ErrorProps {
  statusCode?: number;
}

const Error: NextPage<ErrorProps> = ({ statusCode }) => {
  return (
    <p>
      {statusCode
        ? `An error ${statusCode} occurred on server`
        : "An error occurred on client"}
    </p>
  );
};

Error.getInitialProps = ({ res, err }: NextPageContext) => {
  const statusCode = res ? res.statusCode : err ? err.statusCode : 404;
  return { statusCode };
};

export default Error;

小結

404 跟 500 的客製化頁面現在都是以 SSG 的方式打包成靜態的 HTML 檔案,可以免除 SSR 需要花時間渲染的成本。由於是 SSG,所以想要傳入資料至 404 或 500 的頁面中目前暫時做不到,有看到 GitHub discussion 有一篇在講述希望可以提供這個功能,未來也許有一天能看到這個功能被實現。

在 Next.js 中除了能夠客製化 404 跟 500 頁面之外,也可以客製處理其他錯誤的頁面,而且同時包含客戶端與伺服器端的錯誤。error page 的功用可以跟 error boundary 做切分,error page 處理顯示頁面,error boundary 處理攔截錯誤做進一步的處理,所以兩者並不會相沖。

Reference


上一篇
Day23 - 在 Next.js 中如何共用 Layout
下一篇
Day25 - 如何在 Next.js 中正確地使用 lodash,使用 babel-plugin-import
系列文
從零開始學習 Next.js30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

1 則留言

0
AndrewYEE
iT邦新手 3 級 ‧ 2023-02-17 19:46:15

補充: error page檔名為pages/_error.js

我要留言

立即登入留言